#include <stdlib.h>
#include <string>
#include <iostream>
#include <rise/common/exmacros.h>
#include <rise/common/Log.h>
#include <rise/common/Exception.h>
#include <rise/common/DataEncoder.h>
#include <staff/common/Value.h>
#include <staff/common/QName.h>
#include <staff/common/Attribute.h>
#include <staff/common/DataObject.h>
#include <staff-mq/client/Publisher.h>


int main(int nArgs, char* szArgs[])
{
  std::string sServerHost = "127.0.0.1";
  unsigned short ushServerPort = 8768;

  for (int nArg = 1; nArg < nArgs; ++nArg)
  {
    if(szArgs[nArg])
    {
      const std::string& sArg = std::string(szArgs[nArg]);
      if (sArg.substr(0, 2) == "-s")
      {
        sServerHost = sArg.substr(2);
      }
      else
      if (sArg.substr(0, 2) == "-p")
      {
        ushServerPort = static_cast<unsigned short>(atoi(sArg.substr(2).c_str()));
      }
      else
      if (sArg.substr(0, 2) == "-h")
      {
        std::cerr << "Publisher sample.\n\n"
            << szArgs[0] << "[ -h][ -s<Server host>][ -p<port>]\n\n";
        return 0;
      }
      else
      {
        std::cerr << "unknown arg: " << sArg << "\n";
        return 1;
      }
    }
  }


  try
  {
    smq::Publisher tPublisher;
    tPublisher.Init("test_publisher", sServerHost, ushServerPort);

    tPublisher.CreateQueue("queue1");
    tPublisher.CreateQueue("queue2");
    tPublisher.CreateQueue("test-queue1");
    tPublisher.CreateQueue("test-queue2");

    // first message type
    {
      staff::CDataObject tdoMsg("msg");
      tdoMsg.CreateChild("int_val1").SetValue(1);
      tdoMsg.CreateChild("double_val1").SetValue(2.3);
      tdoMsg.CreateChild("str_val1").SetValue("test"); // SetText is more efficient

      // for queue1 and queue2 adding binary data
      staff::CDataObject tdoData = tdoMsg.CreateChild("Data");
      {
        std::string sBase64Data; // encoded data

        unsigned char uchData[256]; // our data
        for (int i = 0; i < 256; ++i)
        {
          uchData[i] = i;
        }

        // encoding data to base64 string
        rise::CBase64Encoder::Encode(uchData, sizeof(uchData), sBase64Data);
        // setting data
        tdoData.SetText(sBase64Data);
      }

      // publishing into queue1 and queue2
      std::cout << "Publishing message into \"queue1\"" << std::endl;
      tPublisher.Publish("queue1", tdoMsg);
      std::cout << "Publishing message into \"queue2\"" << std::endl;
      tPublisher.Publish("queue2", tdoMsg);
    }


    // second message type
    {
      staff::CDataObject tdoMsg("msg");
      tdoMsg.CreateChild("int_val1").SetValue(2);
      tdoMsg.CreateChild("double_val1").SetValue(5.1);
      tdoMsg.CreateChild("str_val1").SetValue("testq"); // SetText is more efficient

      // adding attrs for test-queue*
      staff::CAttribute tAttr1("attr_string", "attr_value1");
      tdoMsg.AppendAttribute(tAttr1);
      staff::CAttribute tAttr2("attr_int", 5);
      tdoMsg.AppendAttribute(tAttr2);
      staff::CAttribute tAttr3("attr_double", 3.14);
      tdoMsg.AppendAttribute(tAttr3);

      std::cout << "Publishing message into \"test-*\"" << std::endl;
      tPublisher.Publish("test-*", tdoMsg);
    }

    tPublisher.RemoveQueue("queue1");
    tPublisher.RemoveQueue("queue2");
    tPublisher.RemoveQueue("test-queue1");
    tPublisher.RemoveQueue("test-queue2");
  }
  RISE_CATCH_ALL

  return 0;
}
